<template>
  <div class="pt-layout-table">
    <!-- 表格操作按钮 -->
    <div class="tools" v-if="editable">
      <el-button
        :disabled="!selected.length || selected.length < 2"
        size="small"
        @click="splitCell"
      >拆分</el-button>
      <el-button
        size="small"
        :disabled="!selected.length || selected.length < 2"
        @click="joinCell"
      >合并</el-button>
      <el-button size="small" @click="addRow">加行</el-button>
      <el-button size="small" @click="addColumn">加列</el-button>
      <el-button size="small" :disabled="!selected.length" @click="delRows">删行</el-button>
      <el-button size="small" :disabled="!selected.length" @click="delColumns">删列</el-button>
    </div>
    <!-- 布局表格 -->
    <table
      ref="table"
      cellspacing="0"
      cellpadding="0"
      :style="{
        height: editable ? 'calc(100% - 53px)' : '100%'
      }"
    >
      <tr
        v-for="(row, ri) in grids"
        :style="{
          height: (100 / grids.length) + '%'
        }"
        :key="ri"
      >
        <td
          v-for="(col, ci) in row"
          :key="ci"
          v-show="col.colspan > 0 && col.rowspan > 0"
          :colspan="col.colspan"
          :rowspan="col.rowspan"
          @mousedown="tdMouseDown(ri, ci)"
          @mousemove="tdMouseMove(ri, ci)"
          :style="{
            backgroundColor: tdBgc(col)
          }"
        ></td>
      </tr>
    </table>
  </div>
</template>

<script>
export default {
  name: "layoutTable",
  props: {
    editable: {
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      grids: [],
      start: null,
      moveStart: null,
      end: null,
      selecting: false,
      selected: [],
      tdMousemoving: false
    };
  },
  computed: {
    // td背景色（用来体现选中的格子）
    tdBgc () {
      return (col) => this.selected.includes(col) ? "#EAECF5" : "#fff";
    }
  },
  watch: {
    grids (n) {
      this.$emit("change", n);
    }
  },
  created () {
    this.reset();
    document.addEventListener("mouseup", this.docMouseUp);
  },
  beforeDestroy () {
    document.removeEventListener("mouseup", this.docMouseUp);
  },
  methods: {
    // 鼠标按下，选择起点
    tdMouseDown (ri, ci) {
      if (!this.editable) {
        return;
      }
      this.start = [ri, ci];
      this.end = null;
      this.selected = [];
      this.selecting = true;
    },
    // 是否空白表格
    isEmpty () {
      if (!this.grids) {
        return true;
      }
      if (this.grids.length === 0) {
        return true;
      }

      var empty = true;

      this.grids.forEach(item => {
        if (item.length > 0) {
          empty = false;
        }
      });

      return empty;
    },
    // 鼠标移动，选择终点
    tdMouseMove (ri, ci) {
      if (!this.selecting || !this.start) {
        return;
      }

      var vm = this;
      var start = vm.start.concat();
      var end = [ri, ci];

      vm.tdMousemoving = true;

      // 反向选择调换start和end
      if (start[0] > end[0]) {
        let swap = start[0];
        start[0] = end[0];
        end[0] = swap;
      }

      if (start[1] > end[1]) {
        let swap = start[1];
        start[1] = end[1];
        end[1] = swap;
      }

      // 取所有选中列里最多的行数
      for (let c = start[1]; c <= ci; c++) {
        let rMax = start[0] - 1;
        for (let r = start[0]; r <= ri; r++) {
          rMax += vm.grids[r][c].rowspan;
        }
        if (rMax > end[0]) {
          end[0] = rMax;
        }
      }

      // 取所有选中行里最多的列数
      for (let r = start[0]; r <= ri; r++) {
        let cMax = start[1] - 1;
        for (let c = start[1]; c <= ci; c++) {
          cMax += vm.grids[r][c].colspan;
        }
        if (cMax > end[1]) {
          end[1] = cMax;
        }
      }

      // 选中所有范围内的格子
      vm.grids.forEach((row, rI) => {
        row.forEach((col, cI) => {
          if (
            rI >= start[0] &&
            rI <= end[0] &&
            cI >= start[1] &&
            cI <= end[1]
          ) {
            vm.selected.push(col);
          }
        });
      });

      vm.moveStart = start;
      vm.moveEnd = end;
    },
    // 鼠标弹起，停止选择
    docMouseUp () {
      if (!this.selecting || !this.start) {
        return;
      }

      if (!this.tdMousemoving) {
        this.end = this.start.concat();
        this.selected = [this.grids[this.start[0]][this.start[1]]];
      } else {
        this.start = this.moveStart;
        this.end = this.moveEnd;
        this.tdMousemoving = false;
      }

      this.selecting = false;
    },
    // 拆分
    splitCell () {
      const vm = this;
      const start = vm.start;
      const end = vm.end;

      // 所有选中格子的 rowspan、colspan 设为1
      if (start[0] === end[0] && start[1] === end[1]) {
        let sCol = vm.grids[start[0]][start[1]];
        let rEnd = start[0] + sCol.rowspan;
        let cEnd = start[1] + sCol.colspan;
        for (let r = start[0]; r < rEnd; r++) {
          for (let c = start[1]; c < cEnd; c++) {
            vm.grids[r][c].rowspan = 1;
            vm.grids[r][c].colspan = 1;
          }
        }
      } else {
        for (let r = start[0]; r <= end[0]; r++) {
          for (let c = start[1]; c <= end[1]; c++) {
            vm.grids[r][c].rowspan = 1;
            vm.grids[r][c].colspan = 1;
          }
        }
      }

      vm.selected = [];
      vm.start = null;
      vm.end = null;
    },
    // 合并
    joinCell () {
      const vm = this;
      const start = vm.start;
      const end = vm.end;
      var rCount = end[0] - start[0];
      var cCount = end[1] - start[1];

      // 选中区域第一行和第一列(rowspan、colspan)设置要合并的总行数和列数
      for (let r = start[0]; r <= end[0]; r++) {
        for (let c = start[1]; c <= end[1]; c++) {
          let col = vm.grids[r][c];
          if (r === start[0] && c === start[1]) {
            col.rowspan = rCount + 1;
            col.colspan = cCount + 1;
            // 其余(rowspan、colspan)设为0
          } else {
            col.colspan = 0;
            col.rowspan = 0;
          }
        }
      }

      console.log(vm.grids);

      vm.selected = [];
      vm.start = null;
      vm.end = null;
    },
    // 删除选中列
    delColumns () {
      const vm = this;
      const cStart = vm.start[1];
      const cEnd = vm.end[1];

      for (let c = cStart; c <= cEnd; c++) {
        for (let r = 0; r < vm.grids.length; r++) {
          let row = vm.grids[r];
          let col = row[cStart];
          if (col.colspan === 0) {
            for (let c2 = cStart; c2 >= 0; c2--) {
              if (row[c2].colspan > 1) {
                row[c2].colspan -= 1;
                break;
              }
            }
            row.splice(cStart, 1);
          } else if (col.colspan > 1) {
            row[cStart + 1].colspan = col.colspan - 1;
            row[cStart + 1].rowspan = col.rowspan;
            row.splice(cStart, 1);
          } else {
            row.splice(cStart, 1);
          }
        }
      }

      vm.selected = [];
      vm.start = null;
      vm.end = null;
    },
    // 删除选中行
    delRows () {
      const vm = this;
      const grids = vm.grids;
      var rStart = vm.start[0];
      var rEnd = vm.end[0];

      for (let r = rStart; r <= rEnd; r++) {
        for (let c = 0; c < grids[rStart].length; c++) {
          let row = grids[rStart];
          let col = row[c];

          if (col.rowspan === 0) {
            for (let r2 = rStart; r2 >= 0; r2--) {
              let col2 = grids[r2][c];
              if (col2.rowspan > 1) {
                col2.rowspan -= 1;
              }
            }
          }

          if (col.rowspan > 1) {
            let col2 = grids[rStart + 1][c];
            col2.rowspan = col.rowspan - 1;
            col2.colspan = col.colspan;
          }
        }
      }

      grids.splice(rStart, 1);

      vm.selected = [];
      vm.start = null;
      vm.end = null;
    },
    // 添加行
    addRow () {
      const vm = this;
      const grids = vm.grids;
      const rIndex = vm.start[0] - 1;
      const cols = [];

      if (vm.isEmpty()) {
        vm.grids = [
          [
            { rowspan: 1, colspan: 1 }
          ]
        ];
        return;
      }

      // 如果选的是第一行
      if (rIndex < 0) {
        grids[0].forEach(() => {
          cols.push({
            rowspan: 1,
            colspan: 1
          });
        });
        grids.splice(0, 0, cols);
        return;
      }

      for (let c = 0; c < grids[rIndex].length; c++) {
        let col = grids[rIndex][c];

        if (col.rowspan !== 1) {
          if (col.rowspan !== 0) {
            col.rowspan += 1;
          }
          cols.push({
            rowspan: 0,
            colspan: 0
          });
        } else {
          cols.push({
            rowspan: 1,
            colspan: 1
          });
        }
      }

      grids.splice(rIndex + 1, 0, cols);

      vm.selected = [];
      vm.start = null;
      vm.end = null;
    },
    // 添加列
    addColumn () {
      const vm = this;
      const cStart = vm.start[1];
      const grids = vm.grids;

      for (let r = 0; r < grids.length; r++) {
        let row = grids[r];
        let col = row[cStart];

        if (col.colspan === 0) {
          for (let c = cStart; c >= 0; c--) {
            if (row[c].colspan > 1) {
              row[c].colspan += 1;
            }
          }
          row.splice(cStart, 0, {
            colspan: 0,
            rowspan: 0
          });
        } else {
          row.splice(cStart, 0, {
            colspan: 1,
            rowspan: 1
          });
        }
      }

      vm.selected = [];
      vm.start = null;
      vm.end = null;
    },
    // 重置
    reset () {
      this.selected = [];
      this.grids = [
        [
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" }
        ],
        [
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" }
        ],
        [
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" }
        ],
        [
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" },
          { colspan: 1, rowspan: 1, url: "", type: "" }
        ]
      ];
    }
  }
};
</script>

<style lang="less" scoped>
.pt-layout-table {
  height: 100%;
  .tools {
    line-height: 32px;
    padding-bottom: 10px;
    border-bottom: 1px solid #ebe9f3;
    margin-bottom: 10px;
  }
  table {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
    td {
      border: 1px solid #d0d7e5;
    }
  }
}
</style>